using System.Collections.Generic;
using System.Linq;
using Kiwi.Container.Caching;
using Kiwi.Container.DependencyInjection;
using Kiwi.Container.Lifetime;
using Kiwi.Container.Scope;

namespace Kiwi.Container
{
    public class ContainerBuilder : IContainerBuilder
    {
        public IComponentCacheResolver DefaultComponentCacheResolver = ComponentCacheResolver.Default;
        public IComponentScope DefaultComponentScope = ComponentScope.Global;
        public IEnumerateDependentProperties DefaultInjectProperties = Properties.None;
        public ILifetimeManager DefaultLifetimeManager = LifetimeManager.Default;

        public ContainerBuilder()
        {
            Registrations = new List<IComponentRegistration>();
            Extensions = new List<IContainerExtension>
                             {
                                 new DisposableLifetimePolicy(),
                                 new StartableLifetimePolicy()
                             };
        }

        public List<IComponentRegistration> Registrations { get; private set; }

        #region IContainerBuilder Members

        public List<IContainerExtension> Extensions { get; private set; }

        public IComponentRegistration Register(IComponentRegistration registration)
        {
            ApplyMissingDefaults(registration);
            Registrations.Add(registration);
            return registration;
        }

        public IContainer CreateContainer(IContainerScope scope)
        {
            foreach (var creator in Registrations)
            {
                ApplyMissingDefaults(creator);
            }
            return new Internal.Container(
                scope,
                Extensions.ToArray(),
                Registrations.ToLookup(c => c.ComponentType.Type, c => c));
        }

        #endregion

        private void ApplyMissingDefaults(IComponentRegistration registration)
        {
            if (registration.ComponentType == null)
            {
                registration.ComponentType = new ComponentType(registration.ActualType);
            }
            if (registration.CacheResolver == null)
            {
                registration.CacheResolver = DefaultComponentCacheResolver;
            }
            if (registration.ComponentScope == null)
            {
                registration.ComponentScope = DefaultComponentScope;
            }
            if (registration.LifetimeManager == null)
            {
                registration.LifetimeManager = DefaultLifetimeManager;
            }
            if (registration.InjectProperties == null)
            {
                registration.InjectProperties = DefaultInjectProperties;
            }
        }
    }
}